﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using DevExpress.Xpo;
using DevExpress.ExpressApp.Security;
using System.Security.Permissions;
using DevExpress.ExpressApp.Editors;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.Base.Security;
using DevExpress.ExpressApp.Filtering;
using DevExpress.Data.Filtering.Helpers;
using DevExpress.ExpressApp;
using System.ComponentModel;
using DevExpress.ExpressApp.DC;
using System.Diagnostics;
using System.Collections;
using System.Reflection;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Data.Helpers;
using DevExpress.Data;

namespace TestPermission.Module
{
    /// <summary>
    /// 成员操作，含没有设置、读、写，指要控制的权限的动作
    /// </summary>
    public enum MemberOperation { NotAssigned, Read, Write }
    /// <summary>
    /// 成员存取权限项目
    /// </summary>
    public class MemberAccessPermissionItem
    {
        private string memberName;
        private Type objectType;
        private MemberOperation operation;
        private ObjectAccessModifier modifier;
        public MemberAccessPermissionItem() { }
        public MemberAccessPermissionItem(MemberAccessPermissionItem source)
        {
            this.memberName = source.memberName;
            this.objectType = source.objectType;
            this.operation = source.operation;
            this.modifier = source.modifier;
        }
        public Type ObjectType
        {
            get { return objectType; }
            set { objectType = value; }
        }
        public string MemberName
        {
            get { return memberName; }
            set { memberName = value; }
        }
        public MemberOperation Operation
        {
            get { return operation; }
            set { operation = value; }
        }
        public ObjectAccessModifier Modifier
        {
            get { return modifier; }
            set { modifier = value; }
        }
    }
    //[NonPersistent,DefaultProperty("PropertyName")]
    //public class ObjectProperty
    //{
    //    public ObjectProperty()
    //    {

    //    }
    //    public ObjectProperty(string propertyName)
    //    {
    //        PropertyName = propertyName;
    //    }
    //    public string PropertyName { get; set; }

    //    public override string ToString()
    //    {
    //        return PropertyName;
    //    }
    //}


    /// <summary>
    /// 成员存取权限，应该是显示在新建菜单上的
    /// </summary>
    [NonPersistent, DefaultProperty("DisplayName")]
    [Custom("Caption", "按成员属性访问权限")]
    public class MemberAccessPermission : PermissionBase
    {
        public MemberAccessPermission() { }
        public MemberAccessPermission(Type objectType, string memberName, MemberOperation operation)
            : this(objectType, memberName, operation, ObjectAccessModifier.Allow)
        {
        }
        public MemberAccessPermission(Type objectType, string memberName, MemberOperation operation, ObjectAccessModifier modifier)
        {
            this.ObjectType = objectType;
            this.MemberName = memberName;
            this.Operation = operation;
            this.Modifier = modifier;
        }

        public string DisplayName { get { return this.ToString(); } }
        private List<MemberAccessPermissionItem> items = new List<MemberAccessPermissionItem>();
        private MemberAccessPermissionItem GetDesignModeItem()
        {
            if (items.Count > 1)
            {
                throw new InvalidOperationException();
            }
            if (items.Count == 0)
            {
                items.Add(new MemberAccessPermissionItem());
            }
            return items[0];
        }
        private List<MemberAccessPermissionItem> CloneItems()
        {
            List<MemberAccessPermissionItem> clonedItems = new List<MemberAccessPermissionItem>();
            foreach (MemberAccessPermissionItem item in items)
            {
                clonedItems.Add(new MemberAccessPermissionItem(item));
            }
            return clonedItems;
        }

        public override System.Security.IPermission Union(System.Security.IPermission target)
        {
            MemberAccessPermission result = (MemberAccessPermission)Copy();
            result.items.AddRange(((MemberAccessPermission)target).CloneItems());
            return result;
        }
        public override bool IsSubsetOf(System.Security.IPermission target)
        {
            if (base.IsSubsetOf(target))
            {
                foreach (MemberAccessPermissionItem targetItem in ((MemberAccessPermission)target).items)
                {
                    if (targetItem.ObjectType == ObjectType
                        && targetItem.MemberName == MemberName
                        && targetItem.Operation == Operation)
                    {
                        return targetItem.Modifier == Modifier;
                    }
                }
                return true;
            }
            return false;
        }
        [TypeConverter(typeof(PermissionTargetBusinessClassListConverter)),ImmediatePostData]
        public Type ObjectType
        {
            get { return GetDesignModeItem().ObjectType; }
            set {
                
                GetDesignModeItem().ObjectType = value;
            }
        }
        [Custom("PredefinedValues", "空")]
        public string MemberName
        {
            get { return GetDesignModeItem().MemberName; }
            set
            {
                GetDesignModeItem().MemberName = value;
            }
        }
        //protected IList<ObjectProperty> Members
        //{
        //    get
        //    {
        //        IList<ObjectProperty> list = new List<ObjectProperty>();
        //        if (ObjectType != null)
        //        {
        //            PropertyInfo[] properties = ObjectType.GetProperties(BindingFlags.Public|BindingFlags.Instance|BindingFlags.DeclaredOnly);
        //            foreach (var item in properties)
        //            {
        //                //[item.GetCustomAttributes(typeof(BrowsableAttribute),true)]
        //                ObjectProperty _property = new ObjectProperty(item.Name);
        //                list.Add(_property);
        //            }
        //        }
        //        return list;
        //    }
        //}
        public MemberOperation Operation
        {
            get { return GetDesignModeItem().Operation; }
            set { GetDesignModeItem().Operation = value; }
        }
        public ObjectAccessModifier Modifier
        {
            get { return GetDesignModeItem().Modifier; }
            set { GetDesignModeItem().Modifier = value; }
        }
        public override System.Security.SecurityElement ToXml()
        {
            SecurityElement result = base.ToXml();
            SecurityElement itemElement = new SecurityElement("MemberAccessPermissionItem");
            itemElement.AddAttribute("Operation", Operation.ToString());
            itemElement.AddAttribute("ObjectType", (ObjectType != null) ? ObjectType.ToString() : "");
            itemElement.AddAttribute("Modifier", Modifier.ToString());
            itemElement.AddAttribute("MemberName", MemberName.ToString());
            result.AddChild(itemElement);
            return result;
        }
        public override void FromXml(System.Security.SecurityElement element)
        {
            items.Clear();
            if (element.Children != null)
            {
                if (element.Children.Count != 1)
                {
                    throw new InvalidOperationException();
                }
                SecurityElement childElement = (SecurityElement)element.Children[0];
                ObjectType = ReflectionHelper.FindType(childElement.Attributes["ObjectType"].ToString());
                Operation = (MemberOperation)Enum.Parse(typeof(MemberOperation), childElement.Attributes["Operation"].ToString());
                Modifier = (ObjectAccessModifier)Enum.Parse(typeof(ObjectAccessModifier), childElement.Attributes["Modifier"].ToString());
                MemberName = childElement.Attributes["MemberName"].ToString();
            }
        }
        public override string ToString()
        {
            return ((ObjectType != null) ? ObjectType.Name : "N/A") + "." + MemberName + " - " + Modifier + " " + Operation;
        }
        public override System.Security.IPermission Copy()
        {
            MemberAccessPermission result = new MemberAccessPermission();
            result.items.AddRange(CloneItems());
            return result;
        }
    }
}

